package managed.service.factory;

import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import library.service.LibraryService;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;

import service.impl.VariedLibraryServiceImpl;

public class LibraryManagedServiceFactory implements ManagedServiceFactory {
	private BundleContext bundleContext;
	private Map pid2Service;
	private Map pid2serviceReg;

	// --- Constructors, Getters, Setters --------------------------------------
	public LibraryManagedServiceFactory(BundleContext bundleContext) {
		this.bundleContext = bundleContext;

		System.out.println("[Library_ManagedServiceFactory]: constructor");
		pid2Service = new HashMap();
		pid2serviceReg = new HashMap();

		System.out.println("[Library_ManagedServiceFactory]: name= "
				+ getName());
	}

	// --- ManagedServiceFactory interface implementation ----------------------
	public String getName() {
		return getClass().getName();
	}

	public void updated(String pid, Dictionary properties)
			throws ConfigurationException {
		System.out.println("-------------------------------------------------");
		System.out.println("[Library_ManagedServiceFactory]: "
				+ "updated() method with pid= " + pid);

		// 1. check -> pid2Service.contains(pid)
		// 1.1 if contains -> set to NULL and goto -> 2.create NEW
		// 1.2 if NOT contains goto-> 2.create NEW

		LibraryService libraryService = (LibraryService) pid2Service.get(pid);
		if (libraryService == null) {
			System.out
					.println("[Library_ManagedServiceFactory]: libraryService == null");

			// the requested libService is not registered => create and register
			libraryService = new VariedLibraryServiceImpl();
			pid2Service.put(pid, libraryService);

			ServiceRegistration libServiceReg = bundleContext.registerService(
					LibraryService.class.getName(), libraryService, null);
			if (libServiceReg != null) {
				pid2serviceReg.put(pid, libServiceReg);
				System.out.println("[Library_ManagedServiceFactory]: "
						+ "libServiceReg added.");
			}
		}

		processLibService(libraryService, properties);

	}

	private void processLibService(LibraryService libraryService,
			Dictionary properties) {
		String bookName = (String) properties.get("name");
		// add the book from "properties" in the Library if it is not there.
		if (bookName != null && libraryService.findBookByName(bookName) == null) {

			libraryService.addBook(properties);
			System.out.println("[Library_ManagedServiceFactory]: "
					+ "Book with name:\"" + bookName + "\" "
					+ " and category: \"" + (String) properties.get("category")
					+ "\" has been added to library.");
		} else {
			if (bookName == null) {
				System.out.println("[Library_ManagedServiceFactory]: "
						+ "Input parameter 'properties' is incorrect.");
			}
			if (libraryService.findBookByName(bookName) != null) {
				System.out.println("[Library_ManagedServiceFactory]: "
						+ "The book is already in the library.");
			}
		}

	}

	public void deleted(String pid) {
		System.out.println("-------------------------------------------------");
		System.out
				.println("[ Library_ManagedServiceFactory ]: deleted() method");

		// 1. LibServiceReg unregister
		ServiceRegistration libServiceReg = (ServiceRegistration) pid2serviceReg
				.get(pid);
		if (libServiceReg != null) {
			libServiceReg.unregister();
			pid2serviceReg.remove(pid);

			System.out.println("[ Library_ManagedServiceFactory ]: "
					+ "LibServiceReg with pid: " + pid + " has been removed.");
		}

		// 2. LibService remove
		Object deletionResult = pid2Service.remove(pid);
		if (deletionResult != null) {
			System.out.println("[ Library_ManagedServiceFactory ]: "
					+ "LibService with pid: " + pid + " has been removed.");
		}
	}

	public void cleanUpRegisteredServices() {
		System.out.println("-------------------------------------------------");
		System.out.println("[ Library_ManagedServiceFactory ]: "
				+ "cleanUpRegisteredServices() method");

		// 1. cleanUp "pid2ServiceReg" which contains LibServiceReg instances
		for (Iterator keyIterator = pid2serviceReg.keySet().iterator(); keyIterator
				.hasNext();) {
			String currentKey = (String) keyIterator.next();
			ServiceRegistration libServiceReg = (ServiceRegistration) pid2serviceReg
					.get(currentKey);
			libServiceReg.unregister();

			System.out.println("[ Library_ManagedServiceFactory ]: "
					+ "ServiceReg with PID: " + currentKey
					+ " has been removed.");
		}

		// set to null all libServiceReg-s from the Hashtable
		pid2serviceReg.clear();

		// 2. cleanUp "pid2Service" which contains LibService instances
		pid2Service.clear();

	}
}
